"""
name: node
author: robocky
date: 2016-12-30
description: The decision tree node class.
"""


class Node:
    """Decision tree node."""
    def __init__(self, parent=None, name: str=""):
        """Set up node with parent"""
        self._parent = parent
        self._name = name
        self._branches = {}

    def set_name(self, name):
        self._name = name

    def add_branch(self, attr: str, name: str=""):
        """Add a branch with attr, and return the branch node"""
        if attr not in self._branches:
            branch_node = Node(self, name)
            self._branches[attr] = branch_node
            return branch_node
        else:
            print("The attr '%s' branch is have")
            return None

    def add_leaf(self, attr: str, value):
        """Add a leaf with attr, and set it's value"""
        if attr not in self._branches:
            self._branches[attr] = value
        else:
            print("The attr '%s' branch is have")

    def print_node(self, tabs=1):
        """Print the node and it's branches"""
        blanks = '  ' * tabs
        if tabs is 0:
            print("ROOT: %s" % self._name)
        else:
            print("NODE: %s" % self._name)
        for attr, branch in self._branches.items():
            if isinstance(branch, Node):
                print("%s%s: " % (blanks, attr), end='')
                branch.print_node(tabs + 1)
            else:
                print("%s%s: LEAF: %s" % (blanks, attr, branch))

    def decision(self, data: dict):
        """Decision the data's result using this node"""
        if self._name in data:
            if data[self._name] in self._branches:
                branch = self._branches[data[self._name]]
                if isinstance(branch, Node):
                    return branch.decision(data)
                else:
                    return branch
            else:
                print("Data's %s value %s is not in node %s." % (self._name, data[self._name], self._name))
                return None
        else:
            print("Data des not have %s attr." % self._name)
            return None

    def has_branch(self, attr: str):
        """Return if node has branch with name attr"""
        return attr in self._branches

if __name__ == '__main__':
    or_node = Node(name="A")
    or_node.add_leaf('True', 'True')
    node_af = or_node.add_branch('False', 'B')
    node_af.add_leaf('True', 'True')
    node_af.add_leaf('False', 'False')
    or_node.print_node()
    print("A, B = 'True', 'False', A or B:", or_node.decision({'A': 'True', 'B': 'False'}))
    print("A, B = 'False', 'True', A or B:", or_node.decision({'A': 'False', 'B': 'True'}))
    print("A, B = 'False', 'False', A or B:", or_node.decision({'A': 'False', 'B': 'False'}))
